<?php

declare(strict_types=1);

namespace App\Middleware;

use Hyperf\HttpServer\Response;
use Hyperf\Utils\Context;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class GatewayMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var Response
     */
    protected $response;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $userInfo = $request->getHeaderLine('user');
        $userData = json_decode($userInfo, true);
        if (json_last_error() != JSON_ERROR_NONE || empty($userData['company_id'] ?? '')) {
            return $this->response->withStatus(401)->json([
                'code' => 401,
                'message' => 'AccessToken authentication does not pass',
                'data' => null
            ]);
        }
        $this->setRequestContext($userData);
        return $handler->handle($request);
    }

    /**
     * @param array $userData
     * @return false|mixed|ServerRequestInterface|null
     */
    private function setRequestContext(array $userData)
    {
        $request = Context::get(ServerRequestInterface::class);
        $configs = $this->getGateWayFieldConfigs();
        foreach ($configs as $config) {
            $value = null;
            if (isset($userData[$config['field']])) {
                $value = $this->convertType($config['type'], $userData[$config['field']]);
            }
            $request = $request->withAttribute('gateway_'. $config['name'], $value);
        }
        Context::set(ServerRequestInterface::class, $request);
        return $request;
    }

    /**
     * [
     *    'field' => 'id', 网关参数名
     *    'type' => 'int', request获取的参数类型
     *    'name' => 'user_id' request获取的参数名
     *  ]
     * 获取网关字段配置（固定参数类型，避免上游改动影响下游逻辑）
     * @return array
     */
    private function getGateWayFieldConfigs(): array
    {
        return [
            [
                'field' => 'company_id',
                'type' => 'int',
                'name' => 'company_id',
            ],
            [
                'field' => 'id',
                'type' => 'int',
                'name' => 'user_id'
            ]
        ];
    }

    /**
     * 转换类型
     * @param string $type
     * @param $value
     * @return array|bool|int|mixed|string
     */
    private function convertType(string $type, $value)
    {
        switch ($type) {
            case 'int':
                $value = (int)$value;
                break;
            case 'array':
                $value = (array)$value;
                break;
            case 'bool':
                $value = (bool)$value;
                break;
            case 'string':
                $value = (string)$value;
                break;
        }
        return $value;
    }
}